package com.jt.aop;

import com.jt.anno.CacheFind;
import com.jt.util.ObjectMapperUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.aop.scope.ScopedProxyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.ShardedJedis;

import java.util.Arrays;

@Component  //组件 将类交给spring容器管理
@Aspect     //表达我是一个切面
public class RedisAOP {
    @Autowired
    //private Jedis jedis;              //使用单台redis
    //private ShardedJedis jedis;       //使用redis分片机制
    private JedisCluster jedis;  //引入redis集群
    /*
    实现AOP业务调用
    1.拦截指定的注解
    2.利用环绕通知实现
    实现的步骤：
            1.获取KEY  必须先获取注解 从注解中获取key？
     指定参数名称进行传值，运行期绑定参数类型完成注解的拦截
     joinPoint必须位于参数的第一位
     */
    @Around("@annotation(cacheFind)")  //指定参数名称进行传值，运行期绑定参数类型完成注解的拦截
    public Object around(ProceedingJoinPoint joinPoint, CacheFind cacheFind){
        Object result=null;
        String key=cacheFind.key();
        String args=Arrays.toString(joinPoint.getArgs());
        key=key+"::"+args;
         //校验是否有值
        if (jedis.exists(key)){
            String json=jedis.get(key);
            MethodSignature methodSignature=(MethodSignature)joinPoint.getSignature();
            Class returnType=methodSignature.getReturnType();
            result=ObjectMapperUtil.toObj(json, returnType);
            System.out.println("AOP查询redis缓存");
        }else {
            try {
                result=joinPoint.proceed();
                String json= ObjectMapperUtil.toJSON(result);
                //是否设定超时时间
                if (cacheFind.seconds1()>0){
                    jedis.setex(key,cacheFind.seconds1(), json);
                }else {
                    jedis.set(key, json);
                }
                System.out.println("AOP查询redis缓存");
            }catch (Throwable throwable){
                throwable.printStackTrace();
            }
        }
        return result;
    }







    //公式 aop=切入点表达式 + 通知方法
//    @Pointcut()
//    public void pointCut(){
//
//    }
//    //如何获取目标对象的相关参数
//    @Before("pointCut()")
//    public void before(JoinPoint joinPoint){  //连接点
//        Object target=joinPoint.getTarget();
//        Object[] args=joinPoint.getArgs();
//        String className=joinPoint.getSignature().getDeclaringTypeName();
//        String methodName=joinPoint.getSignature().getName();
//        System.out.println("目标对象："+target);
//        System.out.println("方法参数："+ Arrays.toString(args));
//        System.out.println("类名称："+className);
//        System.out.println("方法名称："+methodName);
//    }


}
